import * as vscode from 'vscode';
/* HACK: use `require` instead of `import` to bypass type checking, for this
 * module originally targets browser use, and has couple of DOM-related types
 * that does not exist in the VSCode Extension context for obvious reasons. */
const QRCode = require('qrcode');
import * as biliapi from './api';
import * as utils from './utils';
import * as vschelper from './vscode-helper';


export interface AuthConfig {
  uid?: number,
  SESSDATA?: string,
  /** @description `Date.toUTCString()` */
  expire_date?: string
}

/**
 * 验证 `vscdd.auth` 中设置的验证信息是否可用（原理是请求用户的第 114514 页关注）
 * @borrows config.vscdd.auth
 */
export async function isLoginValid(): Promise<boolean> {
  let auth = vscode.workspace.getConfiguration('vscdd').get('auth') as AuthConfig;
  if (typeof auth.uid === 'undefined' || typeof auth.SESSDATA === 'undefined'
        || (typeof auth.expire_date !== 'undefined' && new Date() > new Date(auth.expire_date)))
    return false;
  try {
    await biliapi._get_follow_page(auth.uid, 114514, auth.SESSDATA);
  }
  catch (e) {
    if (e.message! === 'no auth')
      return false;
    throw e;
  }
  return true;
}

/**
 * 登录 B 站，获取验证信息字段
 * @borrows config.vscdd.auth
 */
export async function initAuth(force_relogin=false) {
  let auth = vscode.workspace.getConfiguration('vscdd').get('auth') as AuthConfig;
  /* 若已有配置，检查配置是否可用，询问是否更新 */
  if (!force_relogin
        && typeof auth.uid !== 'undefined'
        && typeof auth.expire_date !== 'undefined' && new Date() < new Date(auth.expire_date)) {
    if (await isLoginValid())
      return;
    let choice = await vscode.window.showWarningMessage('当前登录信息无效，是否重新登录？', 'OK', 'Cancel');
    if (typeof choice === 'undefined' || choice === 'Cancel')
      return;
  }
  /* 无可用配置，扫码登录 */
  let qrcode = await biliapi.get_login_qrcode_url();
  /** 在 Output 中显示二维码。
   *  什么？为什么不用 Webview 渲染一个真正的二维码图像出来？
   *  誒就是懒，又不是不能用（
   *  DEPRECATED: Output 显示出来的就是一坨屎：一不能渲染标准制表符；二来实在是太大了 :( */
  let qrcode_display_panel = vscode.window.createWebviewPanel(
    'vscdd.login', 'VSCDD 扫码登录',
    {viewColumn: vscode.ViewColumn.Active}
  );
  qrcode_display_panel.webview.html = `
    <html>
      <body>
        <p>使用手机 Bilibili 客户端扫描下面的二维码以登录 👇</p>
        ${await QRCode.toString(qrcode.url, {type: 'svg', width: 256})}
      </body>
    </html>
  `;
  /** 等待用户扫描，或二维码过期 */
  while (true) {
    /*** 读取二维码扫描信息 */
    try {
      const info = await biliapi.get_login_qrcode_info(qrcode.oauthKey);
      if (info !== undefined && info !== null) {
        /*** 登录成功，保存用户登录信息 */
        auth = {
          uid: info.uid, SESSDATA: info.SESSDATA,
          expire_date: info.expire_date.toUTCString()
        };
        await vschelper.updateConfiguration('vscdd.auth', auth);
        vscode.window.showInformationMessage('登录成功！');
        break;
      }
    }
    catch (e) {
      if (e.message === 'timeout') {
        vscode.window.showWarningMessage('登录超时！');
        break;
      }
      console.warn(e);
      throw e;
    }
    await utils.sleep(3000);
  }
  qrcode_display_panel.dispose();
}
